﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebGioiThieu.Models;
using System.Web.Security;

namespace WebGioiThieu.Areas.Admin
{
    public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
        public CustomAuthorizeAttribute(string cus)
        {

        }
        public virtual string MasterName { get; set; }

        public virtual string ViewName { get; set; }

        public CustomAuthorizeAttribute()
            : base()
        {
            this.ViewName = "DenyAccess";
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }


            HttpContextBase httpContext = filterContext.HttpContext;
            bool isAuthentication = false,
                isAccess = false;
            if (httpContext.User != null)
            {
                isAuthentication = httpContext.User.Identity.IsAuthenticated;
                if (isAuthentication)
                {
                    object session = httpContext.Session["Permissions"];
                    if (session == null)
                    {
                        session = SetSessionAccess(httpContext);
                    }
                    if (session != null)
                    {
                        string name = MvcHelper.GetCurrentName(httpContext); //"Administrator//IndexSystem"

                        var psg = (session as IEnumerable<AccessRule>);
                        isAccess = psg.Any(m => m.AccessName.Equals(name));
                    }
                    else
                    {
                        isAccess = false;
                    }
                }
            }
            else
            {
                httpContext.Session["Permissions"] = null;
            }

            /*if (AuthorizeCore(filterContext.HttpContext))
            {
                SetCachePolicy(filterContext);
            }
            else*/
            if (!isAuthentication)
            {
                // auth failed, redirect to login page
                filterContext.Result = new HttpUnauthorizedResult();
            }
            else if (isAccess)
            {
                // is authenticated and is in the SuperUser role
                SetCachePolicy(filterContext);
            }
            else if (httpContext.User.Identity.Name == "admin")  //super Administrator
            {
                SetCachePolicy(filterContext);
            }
            else
            {
                filterContext.Result = new ViewResult() { ViewName = this.ViewName };
            }

        }

        public static object SetSessionAccess(HttpContextBase httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException("HttpContextBase is null");
            if (httpContext.User == null)
                throw new ArgumentNullException("User is null");
            string userName = httpContext.User.Identity.Name;
           // System.Web.Security.Roles.GetRolesForUser(userName);
            string[] roles = System.Web.Security.Roles.GetRolesForUser(userName); //new string[0];
            if (roles.Length > 0)
            {
                var permissions = new List<AccessRule>();
                roles.ToList().ForEach(s =>
                {
                    var obj = IntroductionWebDBEntities.Instance.aspnet_Roles.SingleOrDefault(m => m.RoleName == s);
                    permissions.AddRange(obj.AccessRules);
                });
                var ps = permissions.GroupBy(m => m.AccessName).Select(g => g.FirstOrDefault());
                httpContext.Session["Permissions"] = ps.ToList();
            }
            return httpContext.Session["Permissions"];
        }

        protected void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
        {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }

        protected void SetCachePolicy(AuthorizationContext filterContext)
        {
            // ** IMPORTANT **
            // Since we're performing authorization at the action level, the authorization code runs
            // after the output caching module. In the worst case this could allow an authorized user
            // to cause the page to be cached, then an unauthorized user would later be served the
            // cached page. We work around this by telling proxies not to cache the sensitive page,
            // then we hook our custom authorization code into the caching mechanism so that we have
            // the final say on whether a page should be served from the cache.
            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge(new TimeSpan(0));
            cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
        }
    }


}